/*
 * connect_pool.cpp
 *
 *  Created on: 2012-7-5
 *      Author: ThinkPad
 */

#include "connect_pool.h"

connect_pool::connect_pool()
{
		total_count = 0;
		conn_index = 0;
		default_int_count = DFLT_MIN_CONN_SIZ;
}

connect_pool::~connect_pool()
{
	 /**
	  * please add your code here to free buf
	  */
}

/*
 * init net connection
 */
void connect_pool::init_netconnection(netconnection * pconn)
{
     pconn->sockfd = 0;
     pconn->OperationType = OP_INVALID;
     pconn->CurrentEvent = EVENT_INVALID;
     pconn->socket_state = S_CLOSE;
     pconn->iobuf = NULL;
     pconn->ctr_flag = false;
     pconn->events = 0;

     pconn->timeLastAction = time(NULL);
     pconn->timeConnBegin = time(NULL);
     pconn->erroCode = INVALID_ERROR;
     pconn->net_protocl = NET_TCP;
     pconn->connIndex = 0;

     pconn->prev = NULL;
     pconn->next = NULL;

     pconn->list_index = S_FREE_LIST;

     pconn->opLock = new smart_lock();
     pconn->token = NULL;
}

/**
 * add free net connection
 */
int   connect_pool::add_netconnection_pool()
{
		for(int i=0; i < default_int_count ;  i++)
	    {
	          netconnection *pconn = new netconnection();
	          if(pconn == NULL)
	              return NOT_ENOUGH_MEMORY_ERROR;

	          /*init data member*/
	          init_netconnection(pconn);

	          /*alloc io buf*/
	          if(SUCCESS != mempool.alloc_buf(&pconn->iobuf))
	          {
					  delete pconn;
					  pconn = NULL;
					  return NOT_ENOUGH_MEMORY_ERROR;
	          }

	          /*add to free pool*/
	          free_list.push(pconn);
	          total_count ++;
	    }

		return SUCCESS;
}

/*
 *init conn pool
 */
int connect_pool::init_conn_pool(int init_count)
{
		if(!conn_list.init_list(true)
			 || !wait_list.init_list(true)
			 || !free_list.init_list(false))
			 return NOT_ENOUGH_MEMORY_ERROR;

		default_int_count = init_count;

		if(SUCCESS != mempool.init_buf(default_int_count))
			return FAILURE;

		return add_netconnection_pool();
}

/*
 *
 * alloc new net connection ,and add to connection pool
 */
int connect_pool::alloc_connection(netconnection *&pconn)
{
    int ret_value = FAILURE;

    conn_pool_lock.Lock();
    {
    	/*check free pool*/
    	if(free_list.size()  <  10)
    	{
    			this->add_netconnection_pool();
    	}

        /*alloc new sock and overlapex obj*/
        if(free_list.size()  > 0)
        {
            free_list.alloc(&pconn);
        }

        /*add to conn pool*/
        if(pconn != NULL)
        {
				this->conn_index ++;
				pconn->connIndex = conn_index;
				pconn->list_index = S_CONN_LIST;
				conn_list.push(pconn);
				ret_value = SUCCESS;
        }
        else
        {
        		ret_value = NOT_ENOUGH_MEMORY_ERROR;
        }

        conn_pool_lock.Unlock();
    }

    return ret_value;
}

/*
 * free net connection to free pool
 */
int connect_pool::free_connection(netconnection *pconn)
{
    if(pconn == NULL)
    {
        return FAILURE;
    }

    conn_pool_lock.Lock();
    {
        pconn->opLock->Lock();
        {
            if(pconn->OperationType != OP_INVALID)
            {
                /*reset overlaper*/
                pconn->ctr_flag = false;
                pconn->events = 0;
                pconn->socket_state = S_CLOSE;
                pconn->OperationType = OP_INVALID;
                pconn->timeLastAction = time(NULL);
                pconn->timeConnBegin = time(NULL);

                pconn->erroCode = INVALID_ERROR;
                pconn->CurrentEvent = EVENT_INVALID;
                pconn->token = NULL;

                if(pconn->iobuf != NULL)
                {
                    memset(pconn->iobuf->buffer,'\0',pconn->iobuf->buf_len);
                    pconn->iobuf->offset = 0;
                    pconn->iobuf->size = 0;
                }

                conn_list.remove(pconn);

                pconn->list_index = S_FREE_LIST;
                free_list.push(pconn);
            }

            pconn->opLock->Unlock();
        }

        conn_pool_lock.Unlock();
    }

    return SUCCESS;
}


/*
 * connection pool size
 */
int connect_pool::get_free_socket_size()
{
    return free_list.size();
}

int connect_pool::get_total_socket_size()
{
    return this->total_count;
}

/*conn list and wait list swap*/
int connect_pool::switch_to_wait_list(netconnection *pconn)
{
    wait_pool_lock.Lock();
    {
        /*first out*/
        if(pconn->list_index == S_CONN_LIST)
        {
            conn_pool_lock.Lock();
            {
                conn_list.remove(pconn);

                pconn->opLock->Lock();
                {
                    pconn->list_index = S_WAIT_LIST;
                    pconn->opLock->Unlock();
                }

                conn_pool_lock.Unlock();
            }

            /*second in*/
            wait_list.push(pconn);
        }

        /*end*/
        wait_pool_lock.Unlock();
    }

    return SUCCESS;
}

int connect_pool::switch_to_conn_list(netconnection *pconn)
{

    wait_pool_lock.Lock();
    {
        if(pconn->list_index == S_WAIT_LIST)
        {
              /*first out*/
              wait_list.remove(pconn);

               /*second in*/
              conn_pool_lock.Lock();
              {
                  pconn->opLock->Lock();
                  {
                      pconn->list_index = S_CONN_LIST;
                      pconn->opLock->Unlock();
                  }

                  conn_list.push(pconn);

                  conn_pool_lock.Unlock();
              }
        }

        /*end*/
        wait_pool_lock.Unlock();
    }

    return SUCCESS;
}

